XML to Mapping

[ Start > PikeHints > XML to Mapping ] [ Edit this Page | Show Page Versions | Show Formatted ]


The following is a simple demo of the XML Tree parser module. The code reads an XML file, parses it into a tree and then turns it into a pike mapping.

__Note__: Using a tree is fine for small fragments of XML, but can rapidly eat up CPU time and memory. In those cases, you probably want to parse the xml in a streaming manner, only saving the bits you need.

Given the following input file:

{code}


0
OK
askldjfklasdfjlasdf
some uuid data
201204110537
201204110537
1331388234
FALSE

jsmith
TRUE


{code}

The resulting mapping is generated:

{code}
([ /* 1 element */
  "reply": ([ /* 3 elements */
      "contents": ([ /* 7 elements */
          "loaded_plugin_set": "201204110537",
          "msp": "FALSE",
          "plugin_set": "201204110537",
          "scanner_boottime": "1331388234",
          "server_uuid": ">some uuid data",
          "token": "askldjfklasdfjlasdf",
          "user": ([ /* 2 elements */
              "admin": "TRUE",
              "name": "ldillon"
            ])
        ]),
      "seq": "0",
      "status": "OK"
    ])
])

{code}

Here's the code:

{code}
int main()
{
  // parse a text file into a tree
  object t = Parser.XML.Tree.parse_file("test.xml");

  // convert the tree to a mapping
  mapping m = xml_to_mapping(t);

  //  print out the result
  werror("m: %O\n", m);

  return 0;
}

mapping xml_to_mapping(object n)
{
  mapping m = ([]);
  
  // for each child of the tree's root, call the function build_mapping.
  n->iterate_children(build_mapping, m);
  return m;
}

string|mapping build_mapping(mixed children, mixed|void map)
{
  if(!map) map = ([]);

  // if called recursively, handle a whole sub-level of xml.
  if(arrayp(children))
  {
    foreach(children;; mixed child)
    {
      if(child->get_node_type() == Parser.XML.Tree.XML_ELEMENT)
        map[child->get_full_name()] = build_mapping2(child->get_children());
    }

    // if there were some key-value pairs present (like a subtree), we can return them
    if(sizeof(map)) return map;
    // otherwise, assume it was just a value without any subtree.
    else return children->get_text() * "";
  }
  else // if we're called directly from iterate_*(), behave slightly differently. 
  {
    if(children->get_node_type() != Parser.XML.Tree.XML_ELEMENT) return 0;
    map[children->get_full_name()] = build_mapping2(children->get_children());
    return 0;
  }
}

{code}

__Poppa's SimpleXML module__

Provides similar functionality to the PHP simplexml class.

https://github.com/poppa/Pike-Modules/blob/master/Misc.pmod/module.pmod

Powered by PikeWiki2

 
gotpike.org | Copyright © 2004 - 2009 | Pike is a trademark of Department of Computer and Information Science, Linköping University